﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FDSimpleModelGenerator.Common;
using FDSimpleModelGenerator.Entities;
using FDSimpleModelGenerator.Entities.Enums;
using FDSimpleModelGenerator.IServices;

namespace FDSimpleModelGenerator.Services.SqlServer
{
    /// <summary>
    /// Sql Server获取数据库中信息服务
    /// </summary>
    public class SqlServerDatabaseTableInfoService : IDatabaseTableInfoService
    {
        private readonly IExceptionThrowFactory _exceptionThrowFactory;
        private readonly IDbConfigResolver _dbConfigResolver;
        private readonly IDbAccessor _dbAccessor;
        private readonly ICache _cache;

        public DbType DbType => DbType.SqlServer;

        public SqlServerDatabaseTableInfoService(IExceptionThrowFactory exceptionThrowFactory,
            IEnumerable<IDbConfigResolver> dbConfigResolvers, IDbAccessor dbAccessor,
            ICache cache)
        {
            _cache = cache;
            _exceptionThrowFactory = exceptionThrowFactory;
            _dbConfigResolver = dbConfigResolvers.First(r => r.DbType == DbType);
            _dbAccessor = dbAccessor;
        }

        public IList<DbDataType> GetDbDataTypes(DbConfig dbConfig)
        {
            return _cache.Get("SqlServer_DbDataType", () =>
            {
                var connString = _dbConfigResolver.GetConnectionString(dbConfig);
                var sql = "SELECT name,max_length MaxLength,precision FROM sys.types WHERE is_user_defined=0 ORDER BY name";
                _dbAccessor.Init(() => new SqlConnection(connString));
                return _dbAccessor.GetList<DbDataType>(sql); ;
            }, TimeSpan.FromHours(3));
        }

        public IList<string> GetDbTables(DbConfig dbConfig)
        {
            return _cache.Get("SqlServer_DbTables", () =>
            {
                var connString = _dbConfigResolver.GetConnectionString(dbConfig);
                var sql = "SELECT name FROM sysobjects WHERE xtype='u'";
                _dbAccessor.Init(() => new SqlConnection(connString));
                return _dbAccessor.GetList<string>(sql);
            }, TimeSpan.FromMinutes(30));
        }

        public async Task<IList<DbDataType>> GetDbDataTypesAsync(DbConfig dbConfig)
        {
            return await Task.Run(() => GetDbDataTypes(dbConfig));
        }

        public async Task<IList<string>> GetDbTablesAsync(DbConfig dbConfig)
        {
            return await Task.Run(() => GetDbTables(dbConfig));
        }
    }
}
